package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.tanhua.autoconfig.template.OssTemplate;
import com.tanhua.commons.constants.Constants;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.VoicesApi;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.Voice;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.VoiceVo;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.util.List;
import java.util.Set;

/**
 * @author LiuKeLin
 * @title: ReceivingVoiceService
 * @projectName tanhua-practice
 * @description: TODO
 * @date 2022/2/219:10
 */
@Service
public class VoicesService {

    @DubboReference
    private UserInfoApi userInfoApi;

    @Autowired

    private OssTemplate ossTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @DubboReference
    private VoicesApi voiceApi;

    //桃花传音-发送语音
    public Boolean sendVoice(MultipartFile voiceFile) {
        //在Redis中将语音设置一个缓存键,根据当天的时间设置,根据清楚缓存设置清除;
        String today = DateUtil.today();
        String key = Constants.SEND_VOICE_KEY + UserHolder.getUserId() + "_" + today;

        //判断是否redis中是否有数据
        String voiceValue = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.isEmpty(voiceValue)) {
            //为空则设置缓存以一天时间为标准
            stringRedisTemplate.opsForValue().set(key, "3", Duration.ofDays(1));
        } else if (voiceValue.equals("0")) {
            //redis中值为0则返回false今日次数用完
            throw new TanHuaException(ErrorResult.numberVoice());
        }
        //当redis中有值存在则存储的值-1
        stringRedisTemplate.opsForValue().decrement(key);

        //根据当前用户查询用户信息添加tb_Voice表中
        UserInfo userInfo = userInfoApi.findUserInfo(UserHolder.getUserId());
        Voice voice = new Voice();
        voice.setUserId(userInfo.getId());
        voice.setGender(userInfo.getGender());

        try {
            //将文件上传oss阿里云
            String voiceUrl = ossTemplate.upload(voiceFile.getOriginalFilename(), voiceFile.getInputStream());
            voice.setSoundUrl(voiceUrl);
            voiceApi.addVoice(voice);
            return true;
        } catch (IOException e) {
            throw new TanHuaException(ErrorResult.errorVoice());
        }
    }

    public VoiceVo findVoiceVo() {
        String userKey = Constants.USER_VOICE_RECEIVE + UserHolder.getUserId() + "_" + DateUtil.today();
        // 已收听语音用户                                      获取set里面所有的value
        Set<String> receiveUsers = stringRedisTemplate.opsForSet().members(userKey);
        // 当前登录用户
        UserInfo userInfo = userInfoApi.findUserInfo(UserHolder.getUserId());
        // 排除同性同性、自己、已收听
        List<Voice> voices = voiceApi.findVoices(userInfo);
        // 去除好友
        voices.removeIf(voice -> voiceApi.isFreed(userInfo.getId(), voice.getUserId()));
        //设置redis的值为 每天时间加用户id
        String key = Constants.USER_VOICE + UserHolder.getUserId() + "_" + DateUtil.today();
        //听语音次数
        String voiceRedis = stringRedisTemplate.opsForValue().get(key);
        if (StringUtils.isEmpty(voiceRedis)) {
            // 附带过期时间1天
            stringRedisTemplate.opsForValue().set(key, "4", Duration.ofDays(1));
        } else if (StringUtils.equals("1", voiceRedis)) {
            throw new TanHuaException(ErrorResult.numberVoice());
        }
        // 次数减1
        stringRedisTemplate.opsForValue().decrement(key);
        // 没有听过的语音
        if (CollUtil.isEmpty(receiveUsers)) {
            // 附带过期时间1天
            stringRedisTemplate.expire(userKey, Duration.ofDays(1));
            return getVoiceVo(voices, key, userKey);
        }
        // 遍历集合并删除听过的语音
        receiveUsers.forEach(userId -> voices.removeIf(voice -> StringUtils.equals(userId, voice.getUserId().toString())));
        return getVoiceVo(voices, key, userKey);
    }

    private VoiceVo getVoiceVo(List<Voice> voices, String key, String userKey) {
        // 没有语音
        if (CollectionUtils.isEmpty(voices)) {
            throw new TanHuaException(ErrorResult.NoReceiveUsers());
        }
        Voice voice = voices.get(RandomUtils.nextInt(0, voices.size() - 1));
        stringRedisTemplate.opsForSet().add(userKey, voice.getUserId().toString());
        VoiceVo init = VoiceVo.init(userInfoApi.findUserInfo(voice.getUserId()), voice);
        init.setRemainingTimes(Integer.parseInt(stringRedisTemplate.opsForValue().get(key)));
        return init;
    }
}
